/*
 * @Author: Chenbin.Hao
 * @Date: 2023-02-09 10:12:09
 * @!Description: 烟花效果
 */
var canvas = document.getElementById("cas");
var ocas = document.createElement("canvas");
var octx = ocas.getContext("2d");
var ctx = canvas.getContext("2d");
ocas.width = canvas.width = window.innerWidth;
ocas.height = canvas.height = window.innerHeight;
var bigbooms = [];

window.onload = function() {
  initAnimate();
}

function initAnimate() {
  drawBg();

  lastTime = new Date();
  animate();
}

var lastTime;
function animate() {
  /** TODO_此处注意save和restore方法； 
   * globalCompositeOperation--> 属性设置或返回如何将一个源（新的）图像绘制到目标（已有）的图像上
   * globalAlpha--> 属性设置或返回绘图的当前透明值
  */

  ctx.save();
  // 在源图像外显示目标图像。只有源图像外的目标图像部分会被显示，源图像是透明的。
  ctx.globalCompositeOperation = 'destination-out';
  ctx.globalAlpha = 0.1;
  ctx.fillRect(0, 0, canvas.width, canvas.height);
  ctx.restore();

  var newTime = new Date();
  if (newTime - lastTime > 200 + (window.innerHeight - 767) / 2) {
    var random = Math.random() * 10 > 2 ? true : false;
    var x = getRandom(canvas.width / 5, canvas.width * 4 / 5);
    var y = getRandom(50, 200);
    // 满足条件放烟花，否则文字烟花出现
    if (random) {
      var bigboom = new Boom(getRandom(canvas.width / 3, canvas.width * 2 / 3), 2, "#FFF", {x: x, y: y});
      bigbooms.push(bigboom)
    } else {
      console.info('-----------');
      var bigboom = new Boom(getRandom(canvas.width / 3, canvas.width * 2 / 3), 2, "#FFF", {
        x: canvas.width / 2,
        y: 200
      }, document.querySelectorAll(".shape")[parseInt(getRandom(0, document.querySelectorAll(".shape").length))]);
      bigbooms.push(bigboom)
    }
    lastTime = newTime;
  }

  stars.foreach(function() {
    this.paint();
  })

  // 绘制月亮
  drawMoon();

  // TODO_动画开始
  bigbooms.foreach(function(index) {
    var that = this;
    if (!this.dead) {
      this._move();
      this._drawLight();
    } else {
      this.booms.foreach(function(index) {
        if (!this.dead) {
          this.moveTo(index);
        }
        else if (index === that.booms.length - 1) {
          bigbooms.splice(bigbooms.indexOf(that), 1);
        }
      })
    }
  });
  // 一段结束后重新执行
  raf(animate);
};

// 绘制月亮
function drawMoon() {
  var moon = document.getElementById("moon");
  var centerX = canvas.width - 200, centerY = 100, width = 80;
  if (moon.complete) {
    ctx.drawImage(moon, centerX, centerY, width, width)
  } else {
    moon.onload = function() {
      ctx.drawImage(moon, centerX, centerY, width, width)
    }
  }
  // TODO_此段比较迷，感觉可有可无；
  var index = 0;
  for (var i = 0; i < 10; i++) {
    ctx.save();
    ctx.beginPath();
    // context.arc(x,y,r,sAngle,eAngle,counterclockwise); 画圆
    ctx.arc(centerX + width / 2, centerY + width / 2, width / 2 + index, 0, 2 * Math.PI);
    ctx.fillStyle = "rgba(240,219,120,0.005)";
    index += 2;
    // ctx.stroke(); // 注意这块用fill
    ctx.fill();
    ctx.restore();
  }

}

Array.prototype.foreach = function(callback) {
  for (var i = 0; i < this.length; i++) {
    if (this[i] !== null) callback.apply(this[i], [i])
  }
}

var raf = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(callback) {
  window.setTimeout(callback, 1000 / 60);
}

// 点击画布生成一朵烟花
canvas.onclick = function() {
  var x = event.clientX;
  var y = event.clientY;
  var bigboom = new Boom(getRandom(canvas.width / 3, canvas.width * 2 / 3), 2, "#fff", {x: x, y: y});
  bigbooms.push(bigboom);
}
// 烟花升空，发出咻~
var Boom = function(x, r, c, boomArea, shape) {
  this.booms = [];
  this.x = x;
  this.y = (canvas.height + r);
  this.r = r;
  this.c = c;
  this.shape = shape || false;
  this.boomArea = boomArea;
  this.theta = 0;
  this.dead = false;
  this.ba = parseInt(getRandom(80, 200));

  var audio = document.getElementsByTagName("audio");
  for (var i = 0; i < audio.length; i++) {
    if (audio[i].src.indexOf("shotfire") >= 0 && (audio[i].paused || audio[i].ended)) {
      audio[i].play();
      break;
    }
  }
}
// 定义烟花默认属性方法
Boom.prototype = {
  // 绘制一朵朵烟花内部颜色
  _paint: function() {
    ctx.save();
    ctx.beginPath();
    ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI);
    ctx.fillStyle = this.c;
    ctx.fill();
    ctx.restore();
  },
  // 一朵朵烟花向上运动方法
  _move: function() {
    var dx = this.boomArea.x - this.x, dy = this.boomArea.y - this.y;
    this.x = this.x + dx * 0.01;
    this.y = this.y + dy * 0.01;

    if (Math.abs(dx) <= this.ba && Math.abs(dy) <= this.ba) {
      if (this.shape) {
        this._shapBoom();
      }
      else this._boom();
      this.dead = true;
    } else {
      this._paint();
    }
  },
  // 绘制一朵朵烟花外表颜色
  _drawLight: function() {
    ctx.save();
    ctx.fillStyle = "rgba(255,228,150,0.3)";
    ctx.beginPath(); // TODO_遗漏
    ctx.arc(this.x, this.y, this.r + 3 * Math.random() + 1, 0, 2 * Math.PI);
    ctx.fill();
    ctx.restore();
  },
  // 烟花散开,生成五颜六色
  _boom: function() {
    var fragNum = getRandom(100, 300);
    var style = getRandom(0, 10) >= 5 ? 1 : 2;
    var color;
    if (style === 1) {
      color = {
        a: parseInt(getRandom(128, 255)),
        b: parseInt(getRandom(128, 255)),
        c: parseInt(getRandom(128, 255)),
      }
    }

    var fragArea = fragNum;
    var audio = document.getElementsByTagName("audio");
    for (var i = 0; i < audio.length; i++) {
      if (audio[i].src.indexOf("boom") >= 0 && (audio[i].paused || audio[i].ended)) {
        audio[i].play();
        break;
      }
    }
    for (var i = 0; i < fragNum; i++) {
      if (style === 2) {
        color = {
          a: parseInt(getRandom(128, 255)),
          b: parseInt(getRandom(128, 255)),
          c: parseInt(getRandom(128, 255))
        }
      }
      var a = getRandom(-Math.PI, Math.PI);
      var x = getRandom(0, fragArea) * Math.cos(a) + this.x;
      var y = getRandom(0, fragArea) * Math.sin(a) + this.y;
      var radius = getRandom(0, 2);
      var frag = new Frag(this.x, this.y, radius, color, x, y);
      this.booms.push(frag);
    }
  },
  // 祝福语爆炸
  _shapBoom: function() {
    var that = this;
    putValue(ocas, octx, this.shape, 5, function(dots) {
      var dx = canvas.width / 2 - that.x;
      var dy = canvas.height / 2 - that.y;
      for (var i = 0; i < dots.length; i++) {
        color = {
          a: dots[i].a,
          b: dots[i].b,
          c: dots[i].c
        };
        var x = dots[i].x;
        var y = dots[i].y;
        var radius = 1;
        var frag = new Frag(that.x, that.y, radius, color, x - dx, y - dy);
        that.booms.push(frag);
      }
    })
  },
};
// 绘制字体图片
function putValue(canvas, context, ele, dr, callback) {
  context.clearRect(0, 0, canvas.width, canvas.height);
  var img = new Image();
  if (ele.innerHTML.indexOf("img") >= 0) {
    img.src = ele.getElementsByTagName("img")[0].src;
    imgLoad(img, function() {
      context.drawImage(img, canvas.width / 2 - img.width / 2, canvas.height / 2 - img.width / 2);
      dots = getImgData(canvas, context, dr)
    })
  } else {
    var text = ele.innerHTML;
    context.save();
    var fontSize = 100;
    context.font = fontSize + "px 微软雅黑 bold";
    context.textAlign = "center";
    context.textBaseline="middle";
    context.fillStyle = `rgba(${(parseInt(getRandom(128, 255)))}, ${parseInt(getRandom(128, 255))}, ${parseInt(getRandom(128, 255))}, 1)`;
    context.fillText(text, canvas.width / 2, canvas.height / 2);
    context.restore();
    dots = getImgData(canvas, context, dr);
    callback(dots);
  }
}

function imgLoad(img, callback) {
  if (img.complete) {
    callback.call(img);
  } else {
    img.onload = function() {
      callback.call(this);
    }
  }
}

function getImgData(canvas, context, dr) {
  var imgData = context.getImageData(0, 0, canvas.width, canvas.height);
  context.clearRect(0, 0, canvas.width, canvas.height);
  var dots = [];
  for (var x = 0; x < imgData.width; x += dr) {
    for (var y = 0; y < imgData.height; y += dr) {
      var i = (y * imgData.width + x) * 4;
      if (imgData.data[i + 3] > 128) {
        var dot = {
          x: x,
          y: y,
          a: imgData.data[i],
          b: imgData.data[i+1],
          c: imgData.data[i+2]
        }
        dots.push(dot);
      }
    }
  }
  return dots;
}

function getRandom(a, b) {
  return Math.random() * (b - a) + a;
}

var maxRadius = 1, stars = [];
// 绘制背景星星
function drawBg() {
  for (var i = 0; i < 100; i++) {
    var r = Math.random() * maxRadius;
    var x = Math.random() * canvas.width;
    var y = Math.random() * 2 * canvas.height - canvas.height;
    var star = new Star(x, y, r);
    stars.push(star);
    star.paint();
  }
}
// 生成星星
var Star = function(x, y, r) {
  this.x = x;
  this.y = y;
  this.r = r;
}
Star.prototype = {
  paint: function() {
    ctx.save();
    ctx.beginPath();
    ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI);
    ctx.fillStyle =  `rgba(255, 255, 255, ${this.r})`;
    ctx.fill();
    ctx.restore();
  }
};

var focalLength = 250;
var Frag = function(centerX, centerY, radius, color, tx, ty) {
  this.tx = tx;
  this.ty = ty;
  this.x = centerX;
  this.y = centerY;
  this.dead = false;
  this.centerX = centerX;
  this.centerY = centerY;
  this.radius = radius;
  this.color = color;
};

Frag.prototype = {
  paint: function() {
    ctx.fillStyle = `rgba(${this.color.a}, ${this.color.b}, ${this.color.c}, 1)`;
    ctx.fillRect(this.x - this.radius, this.y - this.radius, this.radius * 2, this.radius * 2);
  },
  moveTo: function(index) {
    this.ty = this.ty + 0.3;
    var dx = this.tx - this.x, dy = this.ty - this.y;
    this.x = Math.abs(dx) < 0.1 ? this.tx : (this.x + dx * 0.1);
    this.y = Math.abs(dy) < 0.1 ? this.ty : (this.y + dy * 0.1);
    if (dx === 0 && Math.abs(dy) <= 80) {
      this.dead = true;
    }
    this.paint();
  }
}